package main

import (
	"fmt"
	sentinel "github.com/alibaba/sentinel-golang/api"
	"github.com/alibaba/sentinel-golang/core/flow"
	"log"
	"math/rand"
	"time"
)

func main() {
	// 务必先进行初始化
	err := sentinel.InitDefault()
	if err != nil {
		log.Fatal(err)
	}

	// 配置一条限流规则
	_, err = flow.LoadRules([]*flow.Rule{
		{
			Resource:               "some-test",
			Threshold:              1000,        // 表示流控阈值
			TokenCalculateStrategy: flow.WarmUp, // 采取预热模式
			ControlBehavior:        flow.Reject, // 流控效果为匀速排队
			WarmUpPeriodSec:        30,          // 30s内慢慢增加到Threshold=1000
			WarmUpColdFactor:       3,           // 预热因子，也就是增长的速度或者步长。
		},
	})
	if err != nil {
		fmt.Println(err)
		return
	}

	var globalTotal int
	var passTotal int
	var blockTotal int

	ch := make(chan struct{})
	for i := 0; i < 1000; i++ {
		go func() {
			for {
				globalTotal++
				// 埋点逻辑，埋点资源名为 some-test
				e, b := sentinel.Entry("some-test")
				if b != nil {
					blockTotal++
					// 请求被拒绝，在此处进行处理
					time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond)
				} else {
					passTotal++
					// 请求允许通过，此处编写业务逻辑
					time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond)
					// 务必保证业务结束后调用 Exit
					e.Exit()
				}
			}
		}()
	}

	go func() {
		var oldTotal int // 过去一秒总共处理多少个
		var oldPass int  // 过去一秒总共通过多少个
		var oldBlock int // 过去一秒总限流多少个
		for {

			oneSecondTotal := globalTotal - oldTotal
			oldTotal = globalTotal

			oneSecondPass := passTotal - oldPass
			oldPass = passTotal

			oneSecondBlock := blockTotal - oldBlock
			oldBlock = blockTotal

			time.Sleep(time.Second)
			fmt.Println("total:%d,passed:%d,block:%d", oneSecondTotal, oneSecondPass, oneSecondBlock)
		}
	}()

	<-ch
}
